package com.wzy.portfolio.utils;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wzy.portfolio.model.*;
import lombok.extern.slf4j.Slf4j;
import java.util.*;

/**
 * 股票工具类
 */
@Slf4j
public class StockUtil {

    /**
     * 获取股票当日数据
     * @param code sh600103
     * @return
     */
    public static StockPriceDto stockPrice(String code){
        String url = "http://qt.gtimg.cn/q="+code;
        String body = HttpRequest.get(url).execute().body();
        log.info("----查询股票({})实时价格返回原始报文:{}", code, body);
        String[] data = body.replaceAll("~~~","~").replaceAll("~~","~").split("~");
        StockPriceDto dto = new StockPriceDto();
        dto.setStockName(data[1]);
        dto.setStockCode(code.substring(2));
        dto.setPriceTime(DateTool.DateToString(new Date(),DateStyle.YYYY_MM_DD));
        dto.setYestedayPrice(Double.parseDouble(data[4]));
        dto.setCurrentPrice(Double.parseDouble(data[3]));
        dto.setOpenPrice(Double.parseDouble(data[5]));
        dto.setChangePct(Double.parseDouble(data[31]));
        dto.setMaxPrice(Double.parseDouble(data[32]));
        dto.setMinPrice(Double.parseDouble(data[33]));
        dto.setTurnover(Double.parseDouble(data[35])/10000);
        dto.setVolume(Double.parseDouble(data[36])/10000);
        dto.setAmplitude(Double.parseDouble(data[41]));
        StockPriceDto avg = stockPriceDayAvg(code);
        if(avg != null){
            dto.setAvgPrice5(avg.getAvgPrice5());
            dto.setAvgPrice10(avg.getAvgPrice10());
            dto.setAvgPrice30(avg.getAvgPrice30());
        }
        return dto;
    }

    /**
     * 获取5 10 30日均价
     * @param code
     * @return
     */
    public static StockPriceDto stockPriceDayAvg(String code) {
        int maxRetries = 1;
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                String url = "https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=" + code + "&scale=5&ma=5,10,30&datalen=1";
                String responseBody = HttpRequest.get(url).execute().body();
                JSONArray jsonArray = JSONArray.parseArray(responseBody);
                JSONObject obj = jsonArray.getJSONObject(0);
                StockPriceDto dto = new StockPriceDto();
                dto.setAvgPrice5(obj.getDouble("ma_price5"));
                dto.setAvgPrice10(obj.getDouble("ma_price10"));
                dto.setAvgPrice30(obj.getDouble("ma_price30"));
                return dto;
            } catch (Exception e) {
                log.warn("获取 {} 均价数据第 {} 次尝试失败: {}", code, attempt, e.getMessage());
                if (attempt < maxRetries) {
                    try {
                        Thread.sleep(5000);// 重试延迟时间（毫秒）
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        log.error("重试过程被中断");
                        break;
                    }
                } else {
                    log.error("获取 {} 均价数据失败，已重试 {} 次: {}", code, maxRetries, e.getMessage());
                }
            }
        }
        return null;
    }

    /**
     * 根据时间段获取股票历史每日数据(搜狐数据) 当日数据要16点左右才能查询到
     * @return
     */
    public static List<StockPriceDto> stockHistoryPrice(StockHistoryReq req){
        List<StockPriceDto> dataList = new ArrayList<>();
        String code = "cn_"+req.getStockCode();
        String url = "https://q.stock.sohu.com/hisHq?code="+code +"&start="+req.getStartDate()+"&end="+req.getEndDate()+"&order=D";//order=D 倒序排序
        String body = HttpRequest.get(url).execute().body();
        log.info("----本次查询：url={}  对应数据={}", url, body);
        try {
            JSONArray arr = JSON.parseArray(body);
            for(int m = 0 ; m < arr.size() ;m++){
                JSONObject obj = arr.getJSONObject(m);
                if(!obj.containsKey("hq")){continue;}
                JSONArray hqArr = obj.getJSONArray("hq");
                for(int k = 0 ; k <hqArr.size();k++){
                    StockPriceDto dto = new StockPriceDto();
                    JSONArray tmpArr = hqArr.getJSONArray(k);
                    dto.setStockCode(code.substring(3));
                    dto.setStockName(req.getStockName());
                    dto.setPriceTime(tmpArr.getString(0));
                    dto.setCurrentPrice(Double.parseDouble(tmpArr.getString(2)));
                    dto.setMaxPrice(Double.parseDouble(tmpArr.getString(6)));
                    dto.setMinPrice(Double.parseDouble(tmpArr.getString(5)));
                    dto.setChangePct(Double.parseDouble(tmpArr.getString(4).replaceAll("%","")));
                    dataList.add(dto);
                }
                Thread.sleep(200);
            }
        }catch (Exception e){
            log.error("股票({})处理异常:对应url:{},返回数据:{}", req.getStockName(), url, body);
        }
        return dataList;
    }

    /**
     *
     * 使用Eastmoney API（网络接口）可以获取前复权数据
     * secid	0.000001	0-深交所，1-上交所
     * fqt	1	复权类型：1=前复权（关键参数）
     * klt	101	K线周期：101=日线
     * lmt	10000	返回数据条数限制
     * @return
     */
        public static List<StockPriceDto> eastMoneyApi(StockBaseDto baseDto,String cookie){
        List<StockPriceDto> dataList = new ArrayList<>();
        String baseUrl = "https://push2his.eastmoney.com/api/qt/stock/kline/get?secid=%s&fields1=f1,f2,f3,f4,f5&fields2=f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61&klt=101&fqt=1&beg=%s&end=%s&lmt=10000";
        String url = String.format(baseUrl, getSecid(baseDto.getStockCode()), baseDto.getBeg(), baseDto.getEnd());
        try {
            String body = HttpRequest.get(url) .setConnectionTimeout(30000) .setReadTimeout(60000)
                    .header("User-Agent", UserAgent.generateRandomUserAgent())
                    .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
                    .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                    .header("Accept-Encoding", "gzip, deflate") // 注意服务器可能返回gzip压缩内容
                    .header("Cache-Control", "no-cache")
                    .header("Connection", "keep-alive")
                    .header("Upgrade-Insecure-Requests", "1")
                    .header("Referer", "http://quote.eastmoney.com/")
                    .header("Cookie", cookie) // 使用复制的完整Cookie字符串
                    .execute()
                    .body();
            JSONArray arr = JSON.parseObject(body).getJSONObject("data").getJSONArray("klines");
            if (arr == null || arr.isEmpty()) {
                log.warn("股票[{}]在指定时间段内无数据", baseDto.getStockName());
                return dataList;
            }
            for(int m = 0 ; m < arr.size() ;m++){
                String[] items = arr.getString(m).split(",");
                StockPriceDto dto = new StockPriceDto();
                dto.setStockName(baseDto.getStockName());
                dto.setStockCode(baseDto.getStockCode());
                dto.setPriceTime(items[0]);
                dto.setOpenPrice(Double.parseDouble(items[1]));
                dto.setCurrentPrice(Double.parseDouble(items[2]));
                dto.setMaxPrice(Double.parseDouble(items[3]));
                dto.setMinPrice(Double.parseDouble(items[4]));
                dto.setChangePct(Double.parseDouble(items[8]));
                dto.setVolume(Double.parseDouble(items[5]));
                dto.setTurnover(Double.parseDouble(items[6]) / 100000000.0);
                dto.setAmplitude(Double.parseDouble(items[7]));
                log.info(dto.toString());
                dataList.add(dto);
            }
            return dataList;
        }catch (Exception e){
            log.error("股票:{},从东财网获取数据异常:{}", baseDto.getStockName(), e.getMessage());
            return null;
        }

    }

    /**
     * 根据股票代码自动判断市场并生成secid
     */
    public static String getSecid(String stockCode) {
        if (stockCode.startsWith("6") || stockCode.startsWith("9")) {
            return "1." + stockCode;  // 上交所
        } else {
            return "0." + stockCode;  // 深交所、北交所等
        }
    }

}
